﻿using System.Linq.Expressions;
using FlyingHat.Common.Global;
using FlyingHat.Core.Entities;
using FlyingHat.Model.Models.Global;
using Microsoft.EntityFrameworkCore.Storage;

namespace FlyingHat.Repository.IRepository
{
    public interface IBaseRepository<T> : IDependency where T : BaseEntity, new()
    {
        #region 异步

        /// <summary>
        /// 开启一个事务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
        /// <summary>
        /// 提交事务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task CommitTransactionAsync(CancellationToken cancellationToken = default);
        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task RollbackTransactionAsync(CancellationToken cancellationToken = default);


        /// <summary>
        /// 新增实体并返回ID
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<long> AddReturnIdAsync(T entity, CancellationToken cancellationToken = default);
        /// <summary>
        /// 新增实体并返回受影响的行数
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> AddAsync(T entity, CancellationToken cancellationToken = default);
        /// <summary>
        /// 批量新增实体并返回受影响的行数
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<int> AddRangeAsync(List<T> entities, CancellationToken cancellationToken = default);

        Task<bool> UpdateAsync(T entity, CancellationToken cancellationToken = default);
        /// <summary>
        /// 更新部分字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="predicate">将要更新的字段</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        Task<bool> UpdateAsync(T entity, Expression<Func<T, object>> predicate, CancellationToken cancellationToken = default);
        Task<bool> UpdateAsync(List<T> entities, Expression<Func<T, object>> expression, CancellationToken cancellationToken = default);
        /// <summary>
        /// 排除部分字段更新其他字段
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="predicate">将要排除的字段</param>
        /// <returns></returns>
        Task<bool> UpdateExclude(T entity, Expression<Func<T, object>> predicate, CancellationToken cancellationToken = default);

        Task<bool> DeleteAsync(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default);
        Task<bool> DeleteAsync(long id, CancellationToken cancellationToken = default);

        Task<bool> DeleteAsync(List<long> ids, CancellationToken cancellationToken = default);

        Task<IQueryable<T>> GetAllAsync(CancellationToken cancellationToken = default);

        Task<List<T>> GetListAsync(CancellationToken cancellationToken = default);
        Task<List<T>> GetListAsync(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default);
        Task<IReturnModel> GetListAsync<K, M>(Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, int page, int limit, bool asc = false, CancellationToken cancellationToken = default);
        Task<IReturnModel> GetListAsync<K>(Expression<Func<T, bool>> predicate, Expression<Func<T, K>> keySelector, int page, int limit, bool asc = false, CancellationToken cancellationToken = default);
        Task<int> CountAsync(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default);
        Task<bool> ExistAsync(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default);

        Task<T?> FirstOrDefaultAsync(long id, CancellationToken cancellationToken = default);
        Task<T?> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default);
        #endregion
    }
}
